﻿#region Using

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

#endregion

namespace Vk.Methods.Storage
{
    /// <summary>
    ///     Хранилище
    /// </summary>
    public class Storage
    {
        private readonly Api _api;

        public Storage(Api api)
        {
            _api = api;
        }

        /// <summary>
        ///     Возвращает значение переменной, название которой передано в параметре key.
        ///     Задать значение позволяет метод storage.set.
        /// </summary>
        /// <param name="key">Строковое название переменной длиной не более 100 символов.</param>
        /// <param name="keys">
        ///     Список ключей, разделённых запятыми. Если указан этот параметр, то параметр key не учитывается.
        ///     Максимальное количество ключей не должно превышать 1000 штук.
        /// </param>
        /// <param name="global">
        ///     Указывается 1, если необходимо получить глобальную переменную, а не переменную пользователя. По
        ///     умолчанию 0.
        /// </param>
        /// <returns>
        ///     Возвращает значение одной или нескольких переменных. Если переменная на сервере отсутствует, то будет
        ///     возвращена пустая строка.
        /// </returns>
        /// <remarks>
        ///     Переменные могут храниться в двух областях видимости:
        ///     Пользовательская переменная привязана к пользователю, и только он или сервер приложения может получить к ней
        ///     доступ. Может быть создано не более 1000 переменных для каждого пользователя.
        ///     Глобальная переменная привязана к приложению, и работа с ней не зависит от пользователя. Для того чтобы задать
        ///     глобальную переменную при работе с API от имени пользователя, нужно передать параметр global. Может быть создано не
        ///     более 5000 глобальных переменных.
        /// </remarks>
        public async Task<string> Get(string key, IEnumerable<string> keys = null, bool? global = null)
        {
            var query = new ApiQuery("storage.get")
                .Add("key", key)
                .Add("keys", keys)
                .Add("global", global);

            var result = await _api.Manager.Execute(query);
            return _api.Manager.MethodSuccessed ? result.String() : null;
        }

        /// <summary>
        ///     Возвращает названия всех переменных.
        /// </summary>
        /// <param name="userId">
        ///     ID пользователя, названия переменных которого получаются, в случае если данные запрашиваются
        ///     серверным методом.
        /// </param>
        /// <param name="global">
        ///     Указывается true, если необходимо работать с глобальными переменными, а не с переменными
        ///     пользователя.
        /// </param>
        /// <param name="offset">Смещение, необходимое для выборки определенного подмножества названий переменных. По умолчанию 0. </param>
        /// <param name="count">Количество названий переменных, информацию о которых необходимо получить. </param>
        public async Task<List<string>> GetKeys(int? userId = null,
                                                bool? global = null,
                                                int? offset = null,
                                                int? count = null)
        {
            var query = new ApiQuery("storage.getKeys")
                .Add("user_id", userId)
                .Add("global", global)
                .Add("offset", offset)
                .Add("count", count);

            var result = await _api.Manager.Execute(query);
            return _api.Manager.MethodSuccessed ? result.ChildNodes.Select(x => x.String()).ToList() : null;
        }

        /// <summary>
        ///     Сохраняет значение переменной, название которой передано в параметре key.
        ///     Получить сохранённое значение позволяет метод storage.get.
        /// </summary>
        /// <param name="key">
        ///     Строковое название переменной длиной не более 100 символов. Может содержать символы латинского
        ///     алфавита, цифры, знак тире, нижнее подчёркивание [a-zA-Z_\-0-9].
        /// </param>
        /// <param name="value">Строковое значение переменной, ограниченное 4096 байтами.</param>
        /// <param name="global">
        ///     Указывается 1, если необходимо работать с глобальными переменными, а не с переменными
        ///     пользователя. По умолчанию 0.
        /// </param>
        /// <returns>Возвращает 1 в случае удачного сохранения переменной. </returns>
        /// <remarks>
        ///     Переменные могут храниться в двух областях видимости:
        ///     Пользовательская переменная привязана к пользователю, и только он или сервер приложения может получить к ней
        ///     доступ. Может быть создано не более 1000 переменных для каждого пользователя.
        ///     Глобальная переменная привязана к приложению, и работа с ней не зависит от пользователя. Для того чтобы задать
        ///     глобальную переменную при работе с API от имени пользователя, нужно передать параметр global. Может быть создано не
        ///     более 5000 глобальных переменных.
        /// </remarks>
        public async Task<bool> Set(string key, string value = null, bool? global = null)
        {
            var query = new ApiQuery("storage.set")
                .Add("key", key)
                .Add("value", value)
                .Add("global", global);

            var result = await _api.Manager.Execute(query);
            return _api.Manager.MethodSuccessed && result.Bool().Value;
        }
    }
}